import org.apache.commons.io.FileUtils
import java.io.File

/**
 * 提供一些调用的命令
 * */

/**
 * 项目最开始的时候。执行的初始化调度策略
 * */
fun strategy_init_gitrepo_cmd() {
    SYSTEM_CONFG.gitRepoCfg.forEach { (t, u) ->
        val ctx = GitCtx(
            SYSTEM_CONFG.gitrepobase +
                    File.separator + t + File.separator + "base", u[0].repo, u[0].username, u[0].password
        )
        initRepo(ctx)
    }
}

data class DirSync(val token: String, val fp: String)

/**
 * 本地目录优先，优先使用本地目录替换远程目录
 */
fun strategy_superlocal() {
    SYSTEM_CONFG.gitRepoCfg.forEach { (t, u) ->
        val repobase = SYSTEM_CONFG.gitrepobase + File.separator + t
        evalListener(repobase)
            .forEach {
                FileUtils.copyDirectory(File(it.fp), File(repobase, it.token))
            }
    }
}

/**
 * 优先使用远程目录替换本地目录
 * */
fun strategy_remotesuper() {
    SYSTEM_CONFG.gitRepoCfg.forEach { (t, u) ->
        val repobase = SYSTEM_CONFG.gitrepobase + File.separator + t
        evalListener(repobase)
            .forEach {
                FileUtils.copyDirectory(File(it.fp), File(repobase, it.token))
            }
    }
}

interface NotifySync {
    /**
     * 同步监控文件夹和一级缓存
     * */
    fun sync_level0(fp0: String, fp1: String)

    /**
     * 同步以及缓存和2级缓存
     * */
    fun sync_level1(fp0: String, fp1: String)
}


class SuperLocal : NotifySync {
    override fun sync_level0(fp0: String, fp1: String) {
        FileUtils.copyDirectory(File(fp0), File(fp1))
    }

    override fun sync_level1(fp0: String, fp1: String) {
        FileUtils.copyDirectory(File(fp0), File(fp1))
    }

}

class SuperRemote : NotifySync {
    override fun sync_level0(fp0: String, fp1: String) {
        FileUtils.copyDirectory(File(fp1), File(fp0))
    }

    override fun sync_level1(fp0: String, fp1: String) {
        FileUtils.copyDirectory(File(fp1), File(fp0))
    }
}

enum class CmdType {
    /**
     * 远程文件复制到本地文件夹
     * */
    SYNC_REMOTE_LOCAL_ALL,

    /**
     * 本地文件直接覆盖到远程
     * */
    SYNC_LOCAL_REMOTE_ALL,

    /**
     * 远程文件复制到本地文件夹
     * */
    SYNC_REMOTE_LOCAL,

    /**
     * 本地文件直接覆盖到远程
     * */
    SYNC_LOCAL_REMOTE,

    /**
     * 本地文件和远程混合，优先用本地
     * */
    SYNC_MIX_LOCAL_REMOTE,

    /**
     * 本地文件和远程混合，优先用远程
     * */
    SYNC_MIX_REMOTE_LOCAL
}

annotation class NotifyCmd(val value: CmdType)

@NotifyCmd(CmdType.SYNC_LOCAL_REMOTE_ALL)
fun syncLocalRemoteAll() {
    SYSTEM_CONFG.gitRepoCfg.forEach { (t, u) ->
        val repobase = SYSTEM_CONFG.gitrepobase + File.separator + t
        evalListener(repobase)
            .forEach {
                val level0 = repobase + File.separator + it.token
                val level1 = repobase + File.separator + "base" + File.separator + it.token
                FileUtils.deleteDirectory(File(level0))
                FileUtils.deleteDirectory(File(level1))
                val syncObj = File(it.fp)
                if (syncObj.isDirectory) {
                    FileUtils.copyDirectory(syncObj, File(level0))
                    FileUtils.copyDirectory(syncObj, File(level1))
                } else {
                    FileUtils.copyFile(syncObj, File(level0, syncObj.name))
                    FileUtils.copyDirectory(File(level0), File(level1))
                }
            }
    }
}

@NotifyCmd(CmdType.SYNC_REMOTE_LOCAL_ALL)
fun syncRemoteLocalAll() {
    SYSTEM_CONFG.gitRepoCfg.forEach { (t, u) ->
        val repobase = SYSTEM_CONFG.gitrepobase + File.separator + t
        evalListener(repobase)
            .forEach {
                val syncObj = File(it.fp)
                if (!syncObj.isFile && !syncObj.exists()) {
                    val level0 = repobase + File.separator + it.token
                    val level1 = repobase + File.separator + "base" + File.separator + it.token
                    FileUtils.deleteDirectory(File(level0))
                    FileUtils.copyDirectory(File(level1), File(level0))
                    FileUtils.copyDirectory(File(level0), syncObj)
                }
            }
    }
}

data class SyncCtx(val repo: String, val dirtoken: String)

@NotifyCmd(CmdType.SYNC_LOCAL_REMOTE)
fun syncLocalRemote(ctx: SyncCtx) {
    SYSTEM_CONFG.gitRepoCfg
        .filter { it.key == ctx.repo }
        .forEach { (t, u) ->
            val repobase = SYSTEM_CONFG.gitrepobase + File.separator + t
            evalListener(repobase)
                .filter { it.token == ctx.dirtoken }
                .forEach {
                    val level0 = repobase + File.separator + it.token
                    val level1 = repobase + File.separator + "base" + File.separator + it.token
                    FileUtils.deleteDirectory(File(level0))
                    FileUtils.deleteDirectory(File(level1))
                    val syncObj = File(it.fp)
                    if (syncObj.isDirectory) {
                        FileUtils.copyDirectory(syncObj, File(level0))
                        FileUtils.copyDirectory(syncObj, File(level1))
                    } else {
                        FileUtils.copyFile(syncObj, File(level0, syncObj.name))
                        FileUtils.copyDirectory(File(level0), File(level1))
                    }
                }
        }
}

fun evalListener(repobase: String): List<DirSync> {
    return FileUtils.readLines(File(repobase, "listener.ini"), "utf-8")
        .filter { it.isNotBlank() }
        .map { it.split(",") }
        .map { DirSync(it[0], it[1]) }
}

@NotifyCmd(CmdType.SYNC_REMOTE_LOCAL)
fun syncRemoteLocal(ctx: SyncCtx) {
    SYSTEM_CONFG.gitRepoCfg
        .filter { it.key == ctx.repo }
        .forEach { (t, u) ->
            val repobase = SYSTEM_CONFG.gitrepobase + File.separator + t
            evalListener(repobase)
                .filter { it.token == ctx.dirtoken }
                .forEach {
                    println(it.fp)
                    val syncObj = File(it.fp)
                    if (!syncObj.isFile && !syncObj.exists()) {
                        val level0 = repobase + File.separator + it.token
                        val level1 = repobase + File.separator + "base" + File.separator + it.token
                        FileUtils.deleteDirectory(File(level0))
                        FileUtils.copyDirectory(File(level1), File(level0))
                        FileUtils.copyDirectory(File(level0), syncObj)
                    }
                }
        }
}

fun syncLocalCacheToRemote() {

}
